package com.google.code.flabbyraffle;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

/**
 * Created by IntelliJ IDEA.
 * User: admin
 * Date: 4/28/11
 * Time: 10:30 PM
 * To change this template use File | Settings | File Templates.
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/com/google/code/flabbyraffle/test-spring-config.xml")
public class Raffle_AT {

    private static final Integer JACKPOT_AMOUNT = 50;

    @Resource (name = "raffle")
    private Raffle raffle;
    @Resource (name = "fakeLotteryNumberGenerator")
    private FakeLotteryNumberGenerator fakeLotteryNumberGenerator;

    @Before
    public void setup() {

    }

    //winning numbers ... 21  30  40

    //Each test contains one assert
    //Each test is run independently
    //Format: Setup ... Execute ... Verify
    //Freeman and Pryce say that builder methods are a good thing!  good design

    @Test
    public void oneWinningNumberOnOneWinningTicketMeansOneJackpot() {
        //winning numbers ... 21  30  40
        raffle.uploadTickets("1001, 21");

        raffle.performDrawingFor(JACKPOT_AMOUNT);

        assertThat(raffle.ticketWinningsFor(1001), is(jackpot(1)));
    }

    @Test
    public void oneTicketMatchesAllThreeNumbersMeansThreeJackpots() {
        //winning numbers ... 21  30  40
        raffle.uploadTickets("1001, 30 40 21");

        raffle.performDrawingFor(JACKPOT_AMOUNT);

        assertThat(raffle.ticketWinningsFor(1001), is(jackpot(3)));
    }

    @Test
    public void oneTicketMatchesTwoNumbersMeansTwoJackpots() {
        //winning numbers ... 21  30  40
        raffle.uploadTickets("1001, 21 40 80");

        raffle.performDrawingFor(JACKPOT_AMOUNT);

        assertThat(raffle.ticketWinningsFor(1001), is(jackpot(2)));
    }

    @Test
    public void oneTicketMatchesOneWinningNumberTwiceMeansTwoJackpots() {
        //winning numbers ... 21  30  40
        raffle.uploadTickets("1001, 21 21");

        raffle.performDrawingFor(JACKPOT_AMOUNT);

        assertThat(raffle.ticketWinningsFor(1001), is(jackpot(2)));
    }

    @Test
    public void ticketTwoMatchesAndGetsOneJackpotMatchesButTicketOneGetsNada() {
        //winning numbers ... 21  30  40
        raffle.uploadTickets("1001, 22 22 22 89 78 53 67 \\n 1002, 21");

        raffle.performDrawingFor(JACKPOT_AMOUNT);

        assertThat(raffle.ticketWinningsFor(1002), is(jackpot(1)));
    }

    @Test
    public void twoDifferentTicketsWithOneWinningNumberMeansTwoSeparateJackpots() {
        //winning numbers ... 21  30  40
        raffle.uploadTickets("1001, 21 \\n 1002, 21");

        raffle.performDrawingFor(JACKPOT_AMOUNT);

        assertThat(raffle.ticketWinningsFor(1001), is(jackpot(1)));
        assertThat(raffle.ticketWinningsFor(1002), is(jackpot(1)));
    }

    @Test
    public void twoDifferentTicketsTwoDifferentNumbersMeanTwoSeparateJackpots() {
        //winning numbers ... 21  30  40
        raffle.uploadTickets("1001, 21 \\n 1002, 30");

        raffle.performDrawingFor(JACKPOT_AMOUNT);

        assertThat(raffle.ticketWinningsFor(1001), is(jackpot(1)));
        assertThat(raffle.ticketWinningsFor(1002), is(jackpot(1)));
    }

    @Test
    public void twoDifferentTicketsWithThreeOfTheSameNumberMeansThreeJackpotsAPiece() {
        //winning numbers ... 21  30  40
        raffle.uploadTickets("1001, 21 21 21 \\n 1002, 21 21 21");

        raffle.performDrawingFor(JACKPOT_AMOUNT);

        assertThat(raffle.ticketWinningsFor(1001), is(jackpot(3)));
        assertThat(raffle.ticketWinningsFor(1002), is(jackpot(3)));
    }

    private static int jackpot(int jackpotMultiple) {
        return JACKPOT_AMOUNT * jackpotMultiple;
    }

}
